import { AxiosRequestConfig, AxiosPromise, AxiosResponse } from '../types'
import { parseHeaders } from '../helpers/headers'
import { createError } from '../helpers/error'

function setReq(options: AxiosRequestConfig): AxiosPromise {
  return new Promise((resolve, reject) => {
    const {
      url,
      method = 'get',
      data = null,
      headers,
      responseType,
      timeout,
      cancelToken
    } = options
    const handleResponse = (response: AxiosResponse): void => {
      if (response.status >= 200 && response.status < 300) {
        resolve(response)
      } else {
        reject(
          createError(
            `Request failed width status code ${response.status}`,
            options,
            null,
            xhr,
            response
          )
        )
      }
    }
    if (!url) {
      throw new Error('Url params must')
    }
    const xhr = new XMLHttpRequest()
    // 设置返回值得类型
    if (responseType) {
      xhr.responseType = responseType
    }
    if (timeout) {
      xhr.timeout = timeout
    }
    xhr.open(method.toUpperCase(), url!, true) // true 异步，false 同步

    xhr.onreadystatechange = function() {
      // 没有获取到响应的结果
      if (xhr.readyState !== 4 || xhr.status === 0) {
        return
      }
      const responseHeaders = parseHeaders(xhr.getAllResponseHeaders())
      const responseData = responseType !== 'text' ? xhr.response : xhr.responseText
      const response: AxiosResponse = {
        data: responseData,
        status: xhr.status,
        statusText: xhr.statusText,
        headers: responseHeaders,
        config: options,
        request: xhr
      }
      handleResponse(response)
    }

    xhr.onerror = function() {
      reject(createError('Network Error', options, null, xhr))
    }

    xhr.ontimeout = function() {
      reject(createError(`Timeout o f ${timeout}ms exceeded`, options, 'ECONNABORTED', xhr))
    }

    Object.keys(headers).forEach(name => {
      if (data === null && name.toLowerCase() === 'content-type') {
        delete headers[name]
      } else {
        // 添加用户设置的请求头信息
        xhr.setRequestHeader(name, headers[name])
      }
    })

    if (cancelToken) {
      cancelToken.promise.then(reason => {
        xhr.abort()
        reject(reason)
      })
    }

    xhr.send(data)
  })
}

export default setReq
